package com.qianniu.napi.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.qianniu.napi.admin.entity.Order;
import com.qianniu.napi.admin.entity.Saccount;
import com.qianniu.napi.admin.entity.SaccountFlow;
import com.qianniu.napi.admin.entity.Store;
import com.qianniu.napi.admin.entity.penum.IotypeEnum;
import com.qianniu.napi.admin.entity.penum.XftypeEnum;
import com.qianniu.napi.admin.mapper.SaccountFlowMapper;
import com.qianniu.napi.admin.mapper.SaccountMapper;
import com.qianniu.napi.admin.mapper.StoreMapper;
import com.qianniu.napi.admin.service.IRedisService;
import com.qianniu.napi.admin.service.ISaccountFlowService;
import com.qianniu.napi.admin.service.ISaccountService;
import com.qianniu.napi.common.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

/**
 * <p>
 * 商家账务表 服务实现类
 * </p>
 *
 * @author chenxuebin
 * @since 2018-08-08
 */
@Service
public class SaccountServiceImpl extends ServiceImpl<SaccountMapper, Saccount> implements ISaccountService {

    private final static Logger logger = LoggerFactory.getLogger(SaccountServiceImpl.class);

    @Autowired
    StoreMapper storeMapper;
    @Autowired
    SaccountMapper saccountMapper;
    @Autowired
    SaccountFlowMapper saccountFlowMapper;
    @Autowired
    ISaccountFlowService saccountFlowService;
    @Autowired
    IRedisService redisService;

    public void addSamountInFlow(Order order, XftypeEnum xftype, boolean confirm) {

        Saccount sact = saccountMapper.selectById(order.getSid());
        if (sact == null) {
            sact = initSaccount(order.getMid(), order.getMpid(), order.getSid(), order.getLeagueid());
        }
        SaccountFlow saf = new SaccountFlow();
        saf.setTotal(order.getTotal());
        saf.setAmount(order.getMinprice());
        saf.setMamount(order.getRealpay().subtract(order.getMinprice()));
        saf.setYouhui(order.getDiscount());

        saf.setSn(order.getOrderNo());// 抵扣积分时 = 订单号
        saf.setTransactionid(order.getTransactionId());
        saf.setIotype(IotypeEnum.input.getVal());//积分消费
        saf.setXftype(xftype.getVal());//积分消费
        saf.setXftypename(xftype.getName());//积分消费

        saf.setJifen(order.getJifen());
        saf.setCreatetime(new Date());
        saf.setType(order.getType());

        saf.setMid(order.getMid());
        saf.setMpid(order.getMpid());
        saf.setUid(order.getUid());
        saf.setSid(order.getSid());
        saf.setLeagueid(order.getLeagueid());

        saf.setTradetime(new Date());
        saf.setCreatetime(saf.getTradetime());
        if (confirm) {
            saf.setIsConfirm(1);
            saf.setConfirmDate(new Date());
            saf.setLasttotal(sact.getTotal());
            saf.setLastamount(sact.getAmount());
        } else {
            saf.setIsConfirm(-1);
        }
        saf.setState(1);
        saf.setRuzhang(-1);
        saf.setCreateday(Integer.parseInt(DateUtil.getToday("YYYYMMdd")));
        saf.insert();

        int flag = 0;
        boolean ruzhang = false;
        Saccount nsact = new Saccount();//更新Saccount
        while (flag == 0 && confirm) {

            Long version = sact.getVersion();

            BigDecimal total = sact.getTotal().add(saf.getAmount());//总可用额=可用+不可用=已入账+待入账,可退款
            BigDecimal mamount = sact.getMamount().add(saf.getMamount());//推广营销总费用

            BigDecimal youhui = sact.getYouhui().add(saf.getYouhui()==null?new BigDecimal(0):saf.getYouhui());//总优惠总抵扣费用
            BigDecimal saleAmount = sact.getSaleAmount().add(saf.getTotal());//销售额,不可退款：退款时不联动操作
            BigDecimal unuseAmount = sact.getUnuseAmount().add(saf.getAmount());//销售额,不可退款：退款时不联动操作

            BigDecimal amount = sact.getAmount().add(saf.getAmount());
            BigDecimal fanliing = sact.getFanliing().add(saf.getAmount());
            if (xftype.getVal() == XftypeEnum.sell.getVal()) {
                nsact.setSaleAmount(saleAmount);//累计销售额

                if (order.getGtype().intValue() == 2) {
                    //虚拟商品，直接入账，不需要核销，不需要确认
                    nsact.setTotal(total);
                    nsact.setAmount(amount);
                    ruzhang = true;
                } else {
                    //到店商品，非直接入账
                    nsact.setTotal(total);
                    nsact.setFanliing(fanliing);
                    nsact.setUnuseAmount(unuseAmount);
                    ruzhang = false;
                }
            } else if (xftype.getVal() == XftypeEnum.smaidan.getVal() ||
                    xftype.getVal() == XftypeEnum.maidan.getVal()) {
                //直接入账
                nsact.setTotal(total);
                nsact.setAmount(amount);

                nsact.setSaleAmount(saleAmount);//累计销售额
                ruzhang = true;

            } else if (xftype.getVal() == XftypeEnum.tuijianfan.getVal()) {
                //直接入账,无确认过程
                nsact.setTotal(total);
                nsact.setAmount(amount);
                BigDecimal fanli = sact.getFanli().add(saf.getAmount());//累计佣金
                nsact.setFanli(fanli);
                ruzhang = true;
            } else {
                //非及时入账佣金

            }

            //公共
            nsact.setMamount(mamount);
            nsact.setYouhui(youhui);

            nsact.setModifytime(new Date());
            nsact.setModifier(order.getUid());
            nsact.setVersion(version + 1);
            if (sact.getLeagueid() == null && saf.getLeagueid() != null) nsact.setLeagueid(saf.getLeagueid());


            // ******* 更新账户表 ********
            flag = saccountMapper.update(nsact, new EntityWrapper<Saccount>().eq("sid", order.getSid()).eq("version", version));
            logger.debug(">>>>>>>>>>>>ISaccountService addSaccountFlow.update flag=" + flag);
            if (flag == 0) sact = saccountMapper.selectById(order.getSid());
            else {
                saf.setIsConfirm(1);
                saf.setConfirmDate(new Date());
                saf.setLasttotal(sact.getTotal());
                saf.setLastamount(sact.getAmount());
                if (ruzhang) saf.setRuzhang(1);
                saf.updateById();
            }
        }
    }

    public void addSamountRuzhangFlow(Order order) {

        Saccount sact = saccountMapper.selectById(order.getSid());
        SaccountFlow sactflow = saccountFlowService.selectOne(new EntityWrapper<SaccountFlow>()
                .eq("iotype", IotypeEnum.input.getVal())
                .eq("sn", order.getOrderNo()));
        if (sactflow == null) {
            return;
        }
        if (sact == null) {
            sact = initSaccount(order.getMid(), order.getMpid(), order.getSid(), order.getLeagueid());
        }

        BigDecimal zero = new BigDecimal(0);

        SaccountFlow saf = new SaccountFlow();
        saf.setTotal(zero);
        saf.setAmount(zero);
        saf.setMamount(zero);
        saf.setYouhui(zero);

        saf.setSn(order.getOrderNo());// 抵扣积分时 = 订单号
        saf.setTransactionid(sactflow.getId().toString());
        saf.setIotype(IotypeEnum.input.getVal());//积分消费
        saf.setXftype(XftypeEnum.ruzhang.getVal());//入账流水记录
        saf.setXftypename(XftypeEnum.ruzhang.getName());//入账流水记录

        saf.setJifen(zero);
        saf.setCreatetime(new Date());
        saf.setType(order.getType());

        saf.setMid(order.getMid());
        saf.setMpid(order.getMpid());
        saf.setUid(order.getUid());
        saf.setSid(order.getSid());
        saf.setLeagueid(order.getLeagueid());

        saf.setTradetime(new Date());
        saf.setCreatetime(saf.getTradetime());

        saf.setIotype(0);
        saf.setIsConfirm(-1);
        saf.setState(1);
        saf.setCreateday(Integer.parseInt(DateUtil.getToday("YYYYMMdd")));
        saf.insert();

        int flag = 0;
        Saccount nsact = new Saccount();//更新Saccount
        while (flag == 0) {

            Long version = sact.getVersion();
            BigDecimal amount = sact.getAmount().add(sactflow.getAmount());
            BigDecimal fanliing = sact.getFanliing().subtract(sactflow.getAmount());
            BigDecimal unuseAmount = sact.getUnuseAmount().subtract(sactflow.getAmount());

            nsact.setAmount(amount);
            nsact.setFanliing(fanliing);
            nsact.setUnuseAmount(unuseAmount);

            if (sactflow.getXftype().intValue() == XftypeEnum.sell.getVal()) {
                //销售入账

            } else {
                //其他佣金入账
                BigDecimal fanli = sact.getFanli().add(sactflow.getAmount());//累计佣金
                nsact.setFanli(fanli);
            }

            nsact.setModifytime(new Date());
            nsact.setModifier(order.getUid());
            nsact.setVersion(version + 1);
            if (sact.getLeagueid() == null && saf.getLeagueid() != null) nsact.setLeagueid(saf.getLeagueid());


            // ******* 更新账户表 ********
            flag = saccountMapper.update(nsact, new EntityWrapper<Saccount>().eq("sid", order.getSid()).eq("version", version));
            logger.debug(">>>>>>>>>>>>ISaccountService addSaccountFlow.update flag=" + flag);
            if (flag == 0) sact = saccountMapper.selectById(order.getSid());
            else {
                saf.setIsConfirm(1);
                saf.setRuzhang(0);//平账流水不需要入账
                saf.setConfirmDate(new Date());
                saf.setLasttotal(sact.getTotal());
                saf.setLastamount(sact.getAmount());
                saf.updateById();

                SaccountFlow nsaf = new SaccountFlow();
                nsaf.setId(sactflow.getId());
                nsaf.setRuzhang(1);
                nsaf.setModifytime(new Date());
                nsaf.setModifier(saf.getId());
                nsaf.updateById();
            }
        }
    }

    public void addSaccountOutFlow(SaccountFlow saf) {

        Long uid = saf.getUid();
        Long mid = saf.getMid();
        Long mpid = saf.getMpid();
        Long sid = saf.getSid();
        Long leagueid = saf.getLeagueid();

        Saccount entity = new Saccount();
        entity.setSid(sid);
        Saccount sact = saccountMapper.selectOne(entity);
        if (sact == null) sact = initSaccount(mid, mpid, sid, leagueid);

        saf.setIsConfirm(-1);
        saf.setCreateday(Integer.parseInt(DateUtil.getToday("YYYYMMdd")));
        saf.insert();

        int ret = 0;
        Saccount nsact = new Saccount();
        BigDecimal money = saf.getAmount();
        BigDecimal yxmoney = saf.getMamount();

        while (ret == 0) {

            Long version = sact.getVersion();
            BigDecimal total = sact.getTotal();
            BigDecimal amount = sact.getAmount();
            BigDecimal mamount = sact.getMamount();
            BigDecimal unuseAmount = sact.getUnuseAmount();
            BigDecimal freeze = sact.getFreeze();

            // ******* 待完善 商户账户余额不足的情况处理 *********
            if (saf.getXftype().intValue() == XftypeEnum.withdraw.getVal()) {
                nsact.setTotal(total.subtract(money));
                nsact.setAmount(amount.subtract(money));
                saf.setRuzhang(0);
            } else if (saf.getXftype().intValue() == XftypeEnum.autofanli.getVal()) {
                nsact.setTotal(total.subtract(yxmoney));
                nsact.setAmount(amount.subtract(yxmoney));
                nsact.setMamount(mamount.add(yxmoney));//营销金额
                saf.setRuzhang(0);
            } else if (saf.getXftype().intValue() == XftypeEnum.withdrawing.getVal()) {
                nsact.setAmount(amount.subtract(money));
                nsact.setUnuseAmount(unuseAmount.subtract(money));
                nsact.setFreeze(freeze.subtract(money));
                saf.setRuzhang(-1);
            }

            nsact.setModifytime(new Date());
            nsact.setModifier(uid);
            nsact.setVersion(version + 1);

            saf.setLasttotal(sact.getTotal());
            saf.setLastamount(sact.getAmount());
            saf.setIsConfirm(1);
            saf.setLasttotal(sact.getTotal());
            saf.setLastamount(sact.getAmount());
            saf.setConfirmDate(new Date());
            saf.setModifytime(new Date());
            if (sact.getLeagueid() == null && saf.getLeagueid() != null) nsact.setLeagueid(saf.getLeagueid());

            // ******* 更新账户表 ********
            ret = saccountMapper.update(nsact, new EntityWrapper<Saccount>().eq("sid", sid).eq("version", version));
            logger.debug(">>>withdrawApply maccountService.update ret=" + ret);
            if (ret > 0) {
                saf.insertOrUpdate();
            } else sact = saccountMapper.selectOne(entity);
        }
    }

    public void saccountFlowInConfirm(Order order, Boolean ruzhang) {
        logger.info("----------------------------------------------------saccountFlowConfirm");

        int cout = 0;
        SaccountFlow saf = saccountFlowService.selectOne(new EntityWrapper<SaccountFlow>()
                .eq("sn", order.getOrderNo()));
        Long mid = saf.getMid();
        if (saf != null) {
            Saccount nsact = null;
            Saccount sact = new Saccount();
            while (cout == 0) {
                sact = saccountMapper.selectById(order.getSid());
                if (sact == null) {
                    logger.debug("----------------------------------------start to init maccount");
                    sact = initSaccount(mid, saf.getMpid(), saf.getSid(), saf.getLeagueid());
                }

                nsact = new Saccount();//更新maccountFlowConfirm

                Long version = sact.getVersion();

                BigDecimal amount = sact.getAmount().add(saf.getAmount());
                BigDecimal fanliing = sact.getFanliing().subtract(saf.getAmount());
                BigDecimal unuseAmount = sact.getUnuseAmount().subtract(saf.getAmount());

                nsact.setAmount(amount);
                nsact.setFanliing(fanliing);
                nsact.setUnuseAmount(unuseAmount);

                nsact.setModifytime(new Date());
                nsact.setModifier(saf.getUid());
                nsact.setVersion(version + 1);
                if (sact.getLeagueid() == null && saf.getLeagueid() != null) nsact.setLeagueid(saf.getLeagueid());

                cout = saccountMapper.update(nsact, new EntityWrapper<Saccount>()
                        .eq("sid", saf.getSid()).eq("version", version));
                logger.info("------------Account  cout=" + cout);
                if (cout > 0) {
                    saf.setTransactionid(order.getTransactionId());
                    saf.setIsConfirm(1);
                    saf.setRuzhang(1);
                    saf.setLasttotal(sact.getTotal());
                    saf.setLastamount(sact.getAmount());
                    saf.setConfirmDate(new Date());
                    saf.insertOrUpdate();
                }
            }
        }
    }

    public Saccount initSaccount(Long mid, Long mpid, Long sid, Long leagueid) {

        BigDecimal zero = new BigDecimal(0);

        Saccount act = new Saccount();
        act.setMid(mid);
        act.setMpid(mpid);
        act.setSid(sid);
        Store store = storeMapper.selectById(sid);
        act.setSid(sid);
        act.setSname(store != null ? store.getName() : null);
        act.setLeagueid(redisService.getLeagueid(sid));

        act.setCreatetime(new Date());
        act.setVersion(1l);
        act.setState(1);

        act.setTotal(zero);
        act.setAmount(zero);
        act.setSaleAmount(zero);
        act.setYouhui(zero);
        act.setMamount(zero);
        act.setUnuseAmount(zero);
        act.setFanliing(zero);
        act.setFanli(zero);
        act.setJifen(zero);
        act.setFreeze(zero);
        act.setChargeAmount(zero);
        act.setWithdraw(zero);
        act.setConsume(zero);
        // sms
        act.setSmsmout(new BigDecimal(0));
        act.setSmsmoutTotal(new BigDecimal(0));
        act.setSmsprice(new BigDecimal(0));
        act.setSmstotal(0);
        act.insert();

        logger.debug("========initSaccount=" + JSON.toJSONString(act));
        return act;
    }

    public JSONObject tixian(Long sid, BigDecimal money) {
        JSONObject jo = new JSONObject();


        return jo;
    }
}
